/**
 * @class ICTouchAPI.IMEServices
 * @singleton
 * @extends Object
 * @ignore
 * IME management
 */
dojo.provide("ICTouchAPI.IMEServices");
dojo.declare("ICTouchAPI.IMEServices", null,

    {
        /**
         * @private
         */
        //Hi Soft
        _strLang: "", // "Hangul", "pinyin", "zhuyin"...

        /**
         * @private
         */
        _charSequence: "",

        //Hi Soft
        _maxCharSequenceLength: 6,

        /**
         * @private
         */
        _boolCandidateMode: true, // true -> candidate mode, false -> wordAssociation

        /**
         * @private
         */
        lstIdSession: {},

        //Hi Soft
        imeSessionLang: {
//            Chinese IME
            'pinyin': 0,

//            Japanese IME
            'Katakana': 10,
            'Hiragana': 11,

//            Korea IME
            'Hangul': 20

        },
        /**
         * @private
         */
        constructor: function () {
        },

        /**
         * Ime i18n translate function
         * @private
         */
        ime_: function (toTranslate) {
            return _(toTranslate, "ICTouchAPI", [], "ime");
        },

        /**
         * @private
         */
        getStrLang: function () {
            return this._strLang;
        },

        //Hi Soft
        UTF82Unicode: function Utf82Unicode(strUtf8) {
            var bstr = "";
            var nTotalChars = strUtf8.length; // total chars to be processed.
            var nOffset = 0; // processing point on strUtf8
            var nRemainingBytes = nTotalChars; // how many bytes left to be converted
            var nOutputPosition = 0;
            var iCode, iCode1, iCode2; // the value of the unicode.
            while (nOffset < nTotalChars) {
                iCode = strUtf8.charCodeAt(nOffset);
                if ((iCode & 0x80) == 0) // 1 byte.
                {
                    if (nRemainingBytes < 1) // not enough data
                        break;
                    bstr += String.fromCharCode(iCode & 0x7F);
                    nOffset++;
                    nRemainingBytes -= 1;
                }
                else if ((iCode & 0xE0) == 0xC0) // 2 bytes
                {
                    iCode1 = strUtf8.charCodeAt(nOffset + 1);
                    if (nRemainingBytes < 2 || // not enough data
                        (iCode1 & 0xC0) != 0x80) // invalid pattern
                    {
                        break;
                    }
                    bstr += String
                        .fromCharCode(((iCode & 0x3F) << 6) | (iCode1 & 0x3F));
                    nOffset += 2;
                    nRemainingBytes -= 2;
                } else if ((iCode & 0xF0) == 0xE0) // 3 bytes
                {
                    iCode1 = strUtf8.charCodeAt(nOffset + 1);
                    iCode2 = strUtf8.charCodeAt(nOffset + 2);
                    if (nRemainingBytes < 3 || // not enough data
                        (iCode1 & 0xC0) != 0x80 || // invalid pattern
                        (iCode2 & 0xC0) != 0x80) {
                        break;
                    }
                    bstr += String.fromCharCode(((iCode & 0x0F) << 12)
                        | ((iCode1 & 0x3F) << 6) | (iCode2 & 0x3F));
                    nOffset += 3;
                    nRemainingBytes -= 3;
                } else
                // 4 or more bytes -- unsupported
                    break;
            }
            if (nRemainingBytes != 0) { // bad UTF8 string.
                return "";
            }
            return bstr;
        },
        //Hi soft
        /**
         * Change the language
         * @param {String} language the new language to used. Can be "Hangul", "pinyin" or "zhuyin"
         */
        changeLanguage: function (strLang) {
            this._strLang = strLang;
            var shouldStartIME = ICTouchAPI.keyboardServices.isAPACIMELang(strLang) && 'apac_en' != strLang;
            if (shouldStartIME) {
//				if(!this.lstIdSession[strLang])
                ICTouchAPI.APIServices.IMEManager.startIMESession({params: [this.imeSessionLang[strLang] /* Int corresponding to language */], context: this, callback: this.startedIMESession, callbackParams: {strLang: strLang}});
                this.resetCharSequence();
            }
//            else {
//                var lastLang = ICTouchAPI.keyboardServices.getLastLang();
//                var lastSession = this.lstIdSession[lastLang];
//                if (lastSession) {
//                    ICTouchAPI.APIServices.IMEManager.stopIMESession({params: [lastSession /* Int corresponding to language */], context: this, callback: this.stoppedIMESession, callbackParams: {strLang: lastLang}});
//                }
//            }

            ICTouchAPI.keyboardServices.setIMERequirement(shouldStartIME);
        },

        /**
         * @private
         * */
        stoppedIMESession: function (result, params) {
            if (result && params.strLang) {
                this.lstIdSession[params.strLang] = null;
            } else {
                ICTouchAPI.popupServices.errorPopup(this.ime_("ERROR_IME"), this.ime_("ERROR_STOP_IME_SESSION"), this.ime_("Ok"));
            }

        },
        /**
         * @private
         */
        startedIMESession: function (idSession, params) {
            if (idSession != "NULL")
                this.lstIdSession[params.strLang] = idSession;
            else
                ICTouchAPI.popupServices.errorPopup(this.ime_("ERROR_IME"), this.ime_("ERROR_START_IME_SESSION"), this.ime_("Ok"));
        },

        /**
         * Call core function getIMEWordAssociation
         * @private
         */
        getIMEWordAssociation: function (strWord) {
            this._boolCandidateMode = false;
            ICTouchAPI.APIServices.IMEManager.getIMEWordAssociation({params: [this.lstIdSession[this.getStrLang()], strWord], context: this, callback: this._gotIMEWordAssociation});
        },

        /**
         * Callback of getIMEWordAssociation
         * @private
         */
        _gotIMEWordAssociation: function (arrWordResults) {
            //Hi Soft
            if (!arrWordResults) return;
            var arrCandidates = arrWordResults.candidates;
            ICTouchAPI.keyboardServices.displayCandidates(arrCandidates);
        },

        /**
         * Call core function getIMECandidates
         * @private
         */
        getIMECandidates: function () {
            this._boolCandidateMode = true;
            ICTouchAPI.APIServices.IMEManager.getIMECandidates({params: [this.lstIdSession[this.getStrLang()], this.getCharSequence()], context: this, callback: this._gotIMECandidates});
//          var randNum, randomString;
//          ICTouchAPI.keyboardServices.displayCandidates(randomString());
//            console.log(randomString());
        },

            randNum: function (min, max) {
                var delta;
                if (min == null) min = 0;
                if (max == null) max = 60;
                delta = max - min;
                return Math.floor(Math.random() * delta) + min;
            },

            randomString: function (min, max, m, n) {
                var i, size;
                if (min == null) min = 0;
                if (max == null) max = 100;
                if (m == null) m = 0x4e00;
                if (n == null) n = 0x9ffe;
                size = randNum(min, max);
                return ((function () {
                    var _i, _results;
                    _results = [];
                    for (i = _i = 0; 0 <= size ? _i <= size : _i >= size; i = 0 <= size ? ++_i : --_i) {
                        _results.push(String.fromCharCode(randNum(m, n)));
                    }
                    return _results;
                })()).join('');
            },


        /**
         * Callback of getIMECandidates
         * @private
         */
        //Hi Soft
        _gotIMECandidates: function (IMEResults) {
            //return; //for test
            if (!IMEResults) return;
            var arrCandidates = IMEResults.candidates;
//            if(dojo.isChrome())
//               arrCandidates = this.UTF82Unicode(arrCandidates);
            console.log("candidates=%s", arrCandidates);
            /**
             *  Japanese:
             *      Katakana
             *      Hiragana
             *
             *  Korean: Hangul
             *  Chinese: pinyin
             * */
            switch (this.getStrLang()) {
                case "pinyin" : // Pinyin : we just display it in the candidateList
                    ICTouchAPI.keyboardServices.displayCandidates(arrCandidates);
                    break;
                case "Hangul" : // Hangul : If several candidates, display the last in IME input
                    // Then validate the others and delete letters corresponding to them
                    if (arrCandidates.length > 1) {
                        // push the first one and replace candidate with the last character in arrCandidates
                        //1.push the characters in input zone into input field
                        ICTouchAPI.keyboardServices.pushInputIntoField();
                        //2. update _charSequence to the last character
                        var lastChar = this.getCharSequence()[this.getCharSequenceLength() - 1];
                        this.setCharSequence(lastChar, true);
                    } else { // If 1 candidate, just display it instead of the IME input
                        ICTouchAPI.keyboardServices.replaceChar(arrCandidates, true);
                    }
                    break;

                case "Katakana":
                case "Hiragana":
                    if (arrCandidates.length >= 1) {
                        ICTouchAPI.keyboardServices.displayCharInInputField(arrCandidates, true);
                        this.resetCharSequence();
                    } else if (this.getCharSequenceLength() > 0) {
                        /**
                         *
                         * */
//                        var lastChar = this.getCharSequence()[this.getCharSequenceLength() - 1];
//                        console.log("last Char=", lastChar);
//                        ICTouchAPI.keyboardServices.displayChar(lastChar, true);
                        ICTouchAPI.keyboardServices.displayIMEString(this.getCharSequence());
                    }
                    break;
                default :
                    break;
            }
        },

        /**
         * Not for Hangul
         * Called by keyboardService when we select a candidate
         * @private
         */
        candidateSelected: function (UTF8Char) {
            if (this._boolCandidateMode) { // Result of a getIMECandidate
                // We display the word and launch getIMEWordAssociation
                ICTouchAPI.keyboardServices.displayChar(UTF8Char, false);
                this.getIMEWordAssociation(UTF8Char);
            } else { // Result of a getIMEWordAssociation
                // We replace the last word by the associated word and relaunch getIMEWordAssociation
                ICTouchAPI.keyboardServices.replaceChar(UTF8Char, false);
                this.getIMEWordAssociation(UTF8Char);
            }
            this.resetCharSequence();
        },

        /**
         * Called by keyboard service when user press a key
         * @private
         */
        //Hi soft
        keyPressed: function (UTF8Char) {
            if (this.getCharSequenceLength() >= this._maxCharSequenceLength) return;
            var charToDisplay = UTF8Char;
            if (this.getStrLang() == 'Hangul' && this.getCharSequenceLength() == 0) {
                ICTouchAPI.keyboardServices.displayChar(UTF8Char, true);
                this.setCharSequence(this.getCharSequence() + charToDisplay, false);
                return;
            }
            if (this.getStrLang() == 'pinyin')ICTouchAPI.keyboardServices.displayChar(UTF8Char, true);
            if (charToDisplay != "") this.setCharSequence(this.getCharSequence() + charToDisplay, true);
        },

        /**
         * Set the char sequence with parameter and launch a getIMECandidate if boolean parameter is true
         * @private
         */
        setCharSequence: function (charSequence, boolDoNotGetCandidate) {
            this._charSequence = charSequence;
            if (charSequence.length > 0 && boolDoNotGetCandidate)
                this.getIMECandidates();
        },


        getCharSequence: function () {
            return this._charSequence;
        },

        getCharSequenceLength: function () {
            //Hi Soft
            return this.getCharSequence().length;
        },

        resetCharSequence: function () {
            this.setCharSequence("");
        },

        //Delete the last char
        delChar: function () {
            //Hi Soft
            // if current str lang is Japanese, the request should not be sent
            var sendRequest = ('Katakana' != this.getStrLang() && 'Hiragana' != this.getStrLang());
            this.setCharSequence(this.getCharSequence().slice(0, this.getCharSequenceLength() - 1), sendRequest);
        },

        //Hi Soft
        // Used with Hangul
        // When we validate a word, we have to delete its letters in the char sequence
        deleteFirstLetters: function (intLetters) {
            if (this.getCharSequenceLength() < intLetters)
                this.resetCharSequence();
            else
                this.setCharSequence(this.getCharSequence().slice(intLetters, this.getCharSequenceLength() - intLetters), true);
        },

        zhuyin_ime_translate_input_char: function (strInput, lastChar) {
            var charToSend = 0;
            if (this.getCharSequenceLength() != 0 && strInput[0] == "\u02C9") {
                charToSend = strInput[0];
                /* space is 1st tone if input zone isn't empty */
            }

            if (this.getCharSequenceLength() == 0) { /* this is the 1st input */
                charToSend = strInput[0];

            } else if (this.getCharSequenceLength() == 1) { /* this is the 2nd input */
                if (lastChar == strInput[0]) { // loop machanism
                    charToSend = zhuyin_ime_loop(lastChar, strInput);
                }

                if (charToSend == 0) { // intelligent input
                    charToSend = zhuyin_ime_intelligent_input(strInput);
                }

                if (( charToSend == 0 ) && ( strInput[0] == "\u3127" )) { // inter-vowel or tone?
                    charToSend = zhuyin_ime_inter_vowl_input(lastChar);
                }

                if (charToSend == 0) {
                    charToSend = strInput[0];
                }

            } else { /* this is the 3rd or 4th input */
                switch (strInput[0]) /* tones must be in this position */
                {
                    case "\u310D":
                    case "\u3110":
                    case "\u3117":
                    case "\u3127":
                        charToSend = strInput[2];
                        break;

                    default:
                        charToSend = zhuyin_ime_inter_vowl_input(lastChar);

                        if (charToSend == 0) {
                            charToSend = strInput[0];
                        }
                        break;
                }
            }
            if (charToSend != 0)
                return charToSend;
            else
                return "";
        },

        zhuyin_ime_intelligent_input: function (strInput) {
            switch (strInput[0]) {
                case "\u310D":
                    return "\u02C7"; /* [E] */
                case "\u3110":
                    return "\u02CB"; /* [R] */
                case "\u3117":
                    return "\u02CA"; /* [Y] */
                case "\u3126":
                    return "\u311F"; /* [o] */
                case "\u310B":
                    return "\u3125"; /* [S] */
                case "\u3111":
                    return "\u311A"; /* [F] */
                case "\u3108":
                    return "\u311E"; /* [Z] */
                case "\u3112":
                    return "\u3122"; /* [V] */

                default:
                    return 0;
            }
        },

        zhuyin_ime_inter_vowl_input: function (lastChar) {
            switch (lastChar) {
                case "\u3105": /* [b] */
                case "\u3109": /* [d] */
                case "\u3110": /* [j] */
                case "\u310c": /* [l] */
                case "\u3107": /* [m] */
                case "\u310b": /* [n] */
                case "\u3106": /* [p] */
                case "\u3111": /* [q] */
                case "\u310a": /* [t] */
                case "\u3112": /* [x] */
                    return "\u3127";

                default:
                    return "\u02d9";
            }
        },

        zhuyin_ime_loop: function (lastChar, strInput) {
            var loop_char = 0;

            switch (lastChar) {
                case "\u3105": /* [Q] */
                case "\u3109": /* [W] */
                case "\u3113": /* [T] */
                case "\u311a": /* [F] */
                case "\u3116": /* [G] */
                case "\u3119": /* [H] */
                case "\u311e": /* [Z] */
                case "\u3122": /* [V] */
                    loop_char = strInput[2];
                    break;
                case "\u3106": /* [q] */
                case "\u310a": /* [w] */
                case "\u3114": /* [t] */
                case "\u3111": /* [f] */
                case "\u3115": /* [g] */
                case "\u3118": /* [h] */
                case "\u3108": /* [z] */
                case "\u3112": /* [v] */
                    loop_char = strInput[0];
                    break;
                default:
                    break;
            }

            if (0 != loop_char) {
                this.delChars();
            }

            return loop_char;
        }
    });

ICTouchAPI.IMEServices = new ICTouchAPI.IMEServices();
